#include "freertos_demo.h"

/* FreeRTOS相关头文件 */
#include "FreeRTOS.h"
#include "task.h"

/* 需要用到的其他头文件 */
#include "key.h"
#include "led.h"
#include "usart.h"

/* ###################################################################################*/

/* 启动任务的配置*/
#define START_TASK_STACK 128
#define START_TASK_PRIORITY 1
TaskHandle_t start_task_handler;
StaticTask_t start_task_tcb;
StackType_t start_task_stack[START_TASK_STACK];

/* 任务1的配置*/
#define TASK1_STACK 128
#define TASK1_PRIORITY 2
TaskHandle_t task1_handler;
StaticTask_t task1_tcb;
StackType_t task1_stack[TASK1_STACK];

/* 任务2的配置*/
#define TASK2_STACK 128
#define TASK2_PRIORITY 3
TaskHandle_t task2_handler;
StaticTask_t task2_tcb;
StackType_t task2_stack[TASK2_STACK];

/* 任务3的配置*/
#define TASK3_STACK 128
#define TASK3_PRIORITY 4
TaskHandle_t task3_handler;
StaticTask_t task3_tcb;
StackType_t task3_stack[TASK3_STACK];

/* ###################################################################################*/

/* 任务声明 */
void start_task(void *pvParameters);
void task1(void *pvParameters);
void task2(void *pvParameters);
void task3(void *pvParameters);


/* ###################################################################################*/


/* 两个接口函数 */

/* 空闲任务定义 */
StaticTask_t idle_task_tcb;
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
                                   StackType_t **ppxIdleTaskStackBuffer,
                                   uint32_t *pulIdleTaskStackSize)
{
    *ppxIdleTaskTCBBuffer = &idle_task_tcb;
    *ppxIdleTaskStackBuffer = idle_task_stack;
    *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}

/* 软件定时器定义 */
StaticTask_t timer_task_tcb;
StackType_t timer_task_stack[configMINIMAL_STACK_SIZE];

void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
                                    StackType_t **ppxTimerTaskStackBuffer,
                                    uint32_t *pulTimerTaskStackSize)
{
    *ppxTimerTaskTCBBuffer = &timer_task_tcb;
    *ppxTimerTaskStackBuffer = timer_task_stack;
    *pulTimerTaskStackSize = configMINIMAL_STACK_SIZE;
}


/* ###################################################################################*/


/**
 * freertos的入口函数，启动FreeRTOS
 * @param
 * @param
 * ...
 * @return
 */
void freerttos_start(void)
{
    /* 1.创建启动任务 */
    start_task_handler = xTaskCreateStatic(
        (TaskFunction_t)start_task,
        (char *)"start_task",
        (uint32_t)START_TASK_STACK,
        (void *)NULL,
        (UBaseType_t)START_TASK_PRIORITY,
        (StackType_t *)start_task_stack,
        (StaticTask_t *)&start_task_tcb);

    /* 2.开启任务调度器; 会自动创建空闲任务 */
    vTaskStartScheduler();
}

/**
 * 启动任务，用于创建其他任务
 * @param
 * @param
 * ...
 * @return
 */
void start_task(void *pvParameters)
{
    /* 进入临界区 */
    taskENTER_CRITICAL();

    /* 创建任务1 */
    task1_handler = xTaskCreateStatic(
        (TaskFunction_t)task1,
        (char *)"task1",
        (uint32_t)TASK1_STACK,
        (void *)NULL,
        (UBaseType_t)TASK1_PRIORITY,
        (StackType_t *)task1_stack,
        (StaticTask_t *)&task1_tcb);

    /* 创建任务2 */
    task2_handler = xTaskCreateStatic(
        (TaskFunction_t)task2,
        (char *)"task2",
        (uint32_t)TASK2_STACK,
        (void *)NULL,
        (UBaseType_t)TASK2_PRIORITY,
        (StackType_t *)task2_stack,
        (StaticTask_t *)&task2_tcb);

    /* 创建任务3 */
    task3_handler = xTaskCreateStatic(
        (TaskFunction_t)task3,
        (char *)"task3",
        (uint32_t)TASK3_STACK,
        (void *)NULL,
        (UBaseType_t)TASK3_PRIORITY,
        (StackType_t *)task3_stack,
        (StaticTask_t *)&task3_tcb);

    /* 删除启动任务（自身），启动任务只需要执行一次即可 */
    vTaskDelete(NULL);

    /* 退出临界区 */
    taskEXIT_CRITICAL();
}

/**
 * 任务一，实现LED1每500ms闪烁一次
 * @param
 * @param
 * ...
 * @return
 */
void task1(void *pvParameters)
{
    while (1)
    {
        printf("task1运行...\r\n");
        LED_Toggle(LED1_GPIO_Port, LED1_Pin);
        vTaskDelay(500);
    }
}

/**
 * 任务二，实现LED2每500ms闪烁一次
 * @param
 * @param
 * ...
 * @return
 */
void task2(void *pvParameters)
{
    while (1)
    {
        printf("task2运行...\r\n");
        LED_Toggle(LED2_GPIO_Port, LED2_Pin);
        vTaskDelay(500);
    }
}

/**
 * 任务三，判断KEY1是否按下，按下删除任务一
 * @param
 * @param
 * ...
 * @return
 */
void task3(void *pvParameters)
{
    uint8_t key = 0;
    while (1)
    {
        printf("task3运行...\r\n");
        key = Key_Scan();
        if (key == KEY1_PRESS)
        {
            /* 判断是否已经删过，避免重复删除 */
            if (task1_handler != NULL)
            {
                /* KEY1按下删除task1*/
                printf("任务3运行...\r\n");
                vTaskDelete(task1_handler);
                task1_handler = NULL;
            }
        }
        vTaskDelay(500);
    }
}
